#ifndef _OS_H
#define _OS_H

#define SM_FD_SETSIZE 64

#include <string.h>

typedef struct SM_FD_SET
{
	unsigned int fd_count;
	int fd_array[SM_FD_SETSIZE];
}SM_FD_SET_T;

#define SM_FD_CLR(fd, set) do { \
	unsigned int __i; \
	for (__i = 0; __i < ((SM_FD_SET_T*)(set))->fd_count ; __i++) { \
	if (((SM_FD_SET_T*)(set))->fd_array[__i] == fd) { \
	while (__i < ((SM_FD_SET_T *)(set))->fd_count-1) { \
	((SM_FD_SET_T*)(set))->fd_array[__i] = \
	((SM_FD_SET_T*)(set))->fd_array[__i+1]; \
	__i++; \
	} \
	((SM_FD_SET_T*)(set))->fd_count--; \
	break; \
	} \
	} \
} while(0)

#define SM_FD_SET(fd, set) do { \
	unsigned int __i; \
	for (__i = 0; __i < ((SM_FD_SET_T*)(set))->fd_count; __i++) { \
	if (((SM_FD_SET_T*)(set))->fd_array[__i] == (fd)) { \
	break; \
	} \
	} \
	if (__i == ((SM_FD_SET_T*)(set))->fd_count) { \
	if (((SM_FD_SET_T*)(set))->fd_count < SM_FD_SETSIZE) { \
	((SM_FD_SET_T*)(set))->fd_array[__i] = (fd); \
	((SM_FD_SET_T*)(set))->fd_count++; \
	} \
	} \
} while(0)

#define SM_FD_ZERO(set) (((SM_FD_SET_T*)(set))->fd_count=0)

#define SM_FD_ISSET(fd, set) SM_SockFDIsSet((int)(fd), (SM_FD_SET_T*)(set))

#define SM_INVALID_SOCKET 0
#define SM_SOCK_ERROR (-1)

#define SM_SD_RECEIVE		0x00
#define SM_SEND				0x01
#define SM_BOTH				0x02

#define SM_INADDR_ANY              (unsigned int)0x00000000

struct SM_Timeval 
{
	int    tv_sec;         /* seconds */
	int    tv_usec;        /* and microseconds */
};

//AF_INET
enum
{
	SM_SOCKDOMAIN_AFINET,
	SM_SOCKDOMAIN_AFINET6,
};

//SOCK_STREAM
typedef enum
{
	SM_SOCKTYPE_STREAM,
	SM_SOCKTYPE_DGRAM,
	SM_SOCKTYPE_RAW,
}SM_SOCKTYPE_T;

//IPPROTO_TCP
typedef enum
{
	SM_SOCKPROTO_AUTO,
	SM_SOCKPROTO_TCP,
	SM_SOCKPROTO_UDP,
}SM_SOCKPROTOTYPE_T;

typedef enum
{
	SM_SOL_SOCKET,
	SM_IPPROTO_IP,
	SM_IPPROTO_IPV6,
	SM_IPPROTO_TCP,
}SM_SETOPT_LEVEL;

//SM_SOL_SOCKET option
typedef enum
{
	SM_SO_BROADCAST,
	SM_SO_DEBUG,
	SM_SO_DONTROUTE,
	SM_SO_ERROR,
	SM_SO_KEEPALIVE,
	SM_SO_DONTLINGER,
	SM_SO_LINGER,
	SM_SO_OOBINLINE,
	SM_SO_RCVBUF,
	SM_SO_MAX_MSG_SIZE,
	SM_SO_SNDBUF,
	SM_SO_RCVLOWAT,
	SM_SO_SNDLOWAT,
	SM_SO_RCVTIMEO,
	SM_SO_SNDTIMEO,
	SM_SO_REUSEADDR,
	SM_SO_EXCLUSIVEADDRUSE,
	SM_SO_TYPE,
	SM_SO_BSDCOMPAT,
}SM_SOL_TYPE;

//IPPROTO_IP
typedef enum
{
	SM_IP_HDRINCL,
	SM_IP_OPTINOS,
	SM_IP_TOS,
	SM_IP_TTL,
	SM_IP_ADD_MEMBERSHIP,
	SM_IP_ROP_MEMBERSHIP,
	SM_IP_MULTICAST_IF,
	SM_IP_MULTICAST_TTL,
	SM_IP_MULTICAST_LOOP,
	SM_IP_DROP_MEMBERSHIP,
}SM_IPPROTO_IP_TYPE;

//IPPROTO_TCP
typedef enum
{
	SM_TCP_MAXSEG,
	SM_TCP_NODELAY,
	SM_TCP_CORK,
	SM_TCP_DEFER_ACCEPT,
	SM_TCP_QUICKACK,
}SM_IPPROTO_TCP_TYPE;

typedef enum
{
	SM_FIONBIO,
	SM_FIONREAD,
	SM_SIOCATMARK,
}SM_IOCTL_CMD;

typedef unsigned short SM_PORT_T;
typedef unsigned short SM_SOCKDOMAIN_T;

typedef struct SM_SOCKADDR
{
	SM_SOCKDOMAIN_T			sin_family;
	unsigned char			sin_data[14];
}SM_SOCKADDR_T;

typedef unsigned int SM_SOCKLEN_T;

struct SM_IN_ADDR{
	unsigned int		net_addr;     /* address in network byte order */
};

typedef struct SM_SOCKADDR_IN {
	SM_SOCKDOMAIN_T			sin_family; /* address family: AF_INET */
	SM_PORT_T				sin_port;   /* port in network byte order */
	struct SM_IN_ADDR		sin_addr;   /* internet address */
}SM_SOCKADDR_IN_T;


struct SM_IN6_ADDR{
	unsigned char			net6_addr[16];   /* IPv6 address */
};

struct SM_SOCKADDR_IN6 {
	SM_SOCKDOMAIN_T			sin6_family;   /* AF_INET6 */
	SM_PORT_T				sin6_port;     /* port number */
	unsigned int			sin6_flowinfo; /* IPv6 flow information */
	struct SM_IN6_ADDR	sin6_addr;     /* IPv6 address */
	unsigned int			sin6_scope_id; /* Scope ID (new in 2.4) */
};

struct SM_IP_MRQ
{
	struct SM_IN_ADDR imr_multiaddr;
	struct SM_IN_ADDR imr_interface;
};

struct SM_HOSTENT
{
	char*	h_name;
	char**	h_aliases;
	short	h_addrtype;
	short   h_length;
	char**	h_addr_list;
};

int SM_SockSOcket(int s32Domain, int s32Type, int s32Protocol);
int SM_SockBind(int s32Sockfd, const struct SM_SOCKADDR* psAddr, SM_SOCKLEN_T u32AddrLen);
int SM_SockListen(int s32Sockfd, unsigned int u32Backlog);
int SM_SockConnect(int s32Sockfd, const struct SM_SOCKADDR* psAddr, SM_SOCKLEN_T u32AddrLen);
int SM_SockAccept(int s32Sockfd, struct SM_SOCKADDR* psAddr, SM_SOCKLEN_T* pu32AddrLen);
unsigned int SM_SockSend(int s32Sockfd, const void *buf, unsigned int len, int flags);
unsigned int SM_SockRecv(int s32Sockfd, void *buf, unsigned int len, int flags);
unsigned int SM_SockSendTo(int s32Sockfd, const void *buf, unsigned int len, int flags, const struct SM_SOCKADDR *dest_addr, SM_SOCKLEN_T addrlen);
unsigned int SM_SockRecvFrom(int s32Sockfd, void *buf, unsigned int len, int flags, struct SM_SOCKADDR *src_addr, SM_SOCKLEN_T *addrlen);
int SM_SockClose(int s32Sockfd);
int SM_SockShutdown(int s, int how);
int SM_SockSetSockOpt(int s32Sockfd, int level, int optname, const void* optval, unsigned int optlen);
int SM_SockGetSockOpt(int s32Sockfd, int level, int optname, void* optval, unsigned int* optlen);
int SM_SockIoctlsocket(int s32Sockfd, int cmd, unsigned int* argp);
struct SM_HOSTENT* SM_SockGetHostByName(const char* name);
int SM_SockStartup();
int SM_SockStop();
int SM_SockFDIsSet(int fd, SM_FD_SET_T*set);
int SM_SockSelect(int nfds, SM_FD_SET_T* readfds, SM_FD_SET_T* writefds, SM_FD_SET_T* exceptfds, const struct SM_Timeval* timeout);
unsigned short SM_SockHtons(unsigned short netshort);
unsigned short SM_SockNtohs(unsigned short hostshort);
unsigned long SM_SockHtonl(unsigned long hostlong);
unsigned long SM_SockNtohl(unsigned long netlong);
char* SM_SockInetNtoa(struct SM_IN_ADDR);
int SM_SockInoreSigPipe();


#define SM_IPC_OPEN_EXIST	0x01
#define SM_IPC_OPEN_CREATE	0x02

//ipc msg queue
unsigned int SM_IpcMsgQueueGet(char* name, unsigned int flag);
int SM_IpcMsgQueueRelease(unsigned int id);
int SM_IpcMsgQueueDestroy(unsigned int id);
unsigned int SM_IpcMsgQueueSendMsg(unsigned int id, void* msg, unsigned int msgLength);
unsigned int SM_IpcMsgQueueReceiveMsg(unsigned int id, void* msg, unsigned int* bufferLength, unsigned int timeout);

//ipc shmem
unsigned int SM_IpcShmemGet(char* name,  unsigned int u32Size, void** ppShmem, unsigned int flag);
int SM_IpcShmemRelease(unsigned int id);
int SM_IpcShmemDestroy(unsigned int id);
int SM_IpcShmemRead(unsigned int id, unsigned char* pu8Data, unsigned int u32Len,unsigned int u32Offset);
int SM_IpcShmemWrite(unsigned int id, unsigned char* pu8Data, unsigned int u32Len,unsigned int u32Offset);

//thread
unsigned int SM_OsThreadCreate(unsigned int u32StackSize,
							   unsigned int  (*fStartAddress) (void *), 									            
							   void *ArgList, 
							   unsigned int * phThreadId);

unsigned int SM_OsThreadCreateEx (unsigned int u32StackSize,
							  unsigned int  (*fStartAddress) (void *), 									            
							  void *ArgList, 
							  unsigned int * phThreadId, unsigned int u32Proity);

int SM_OsSetPriority(unsigned int u32Priority);

void SM_OsThreadDestroy(unsigned int hThreadId);

unsigned int SM_OsThreadGetCurId(void);

void SM_OsThreadSleep(unsigned int u32SleepMs);

//sem
void SM_OsSemCreate(unsigned int *pSemaphore, unsigned char *p8Name,
					 unsigned int u32InitialCount);

void SM_OsSemCreateEx(unsigned int *pSemaphore, unsigned char *p8Name,
					  unsigned int u32InitialCount);

void SM_OsSemDestroy (unsigned int *pSemaphore);

int SM_OsSemWait(unsigned int *pSemaphore, unsigned int u32TimeoutMs);

void SM_OsSemRelease(unsigned int *pSemaphore);

unsigned int SM_OsMsecCountGet(void);

unsigned int SM_OsTickCountGet(void);
typedef struct
{
	unsigned int m_u32Year;
	unsigned int m_u32Mon;
	unsigned int m_u32Yday;
	unsigned int m_u32Wday;
	unsigned int m_u32Hour;
	unsigned int m_u32Min;
	unsigned int m_u32Sec;
}SM_TIME_T;
int SM_OsWallTimeGet(SM_TIME_T* pstTime);

void* SM_OsMemAllocate(unsigned int u32Size);

void SM_OsMemFree(void* memblock);

void* SM_OsMemRealloc(void *memblock, unsigned int u32Size);

void SM_SetPrintFileName(const char* ps8FileName);

void SM_Printf(const char *fmt, ... );

void SM_Printf_Error(const char *fmt, ... );

#define SM_DEBUG_COMMON		0
#define SM_DEBUG_ERROR		1
typedef void (*pfDebugOutput)(unsigned int u32Level, const char*);
void SM_RegistorDebugFun(pfDebugOutput);
	

#endif//_OS_H
